<!DOCTYPE html>












  


<html class="theme-next pisces use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2"/>
<meta name="theme-color" content="#222">












<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />






















<link href="/my_blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/my_blog/css/main.css?v=6.3.0" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/my_blog/images/apple-touch-icon-next.png?v=6.3.0">


  <link rel="icon" type="image/png" sizes="32x32" href="/my_blog/images/favicon-32x32-next.png?v=6.3.0">


  <link rel="icon" type="image/png" sizes="16x16" href="/my_blog/images/favicon-16x16-next.png?v=6.3.0">


  <link rel="mask-icon" href="/my_blog/images/logo.svg?v=6.3.0" color="#222">









<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/my_blog/',
    scheme: 'Pisces',
    version: '6.3.0',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: false,
    fastclick: false,
    lazyload: false,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>


  




  <meta name="description" content=".NET 中的异步/多线程/并发处理(1) - 线程本文核心：  如何使用户交互界面具有良好的响应？ 如何最大化利用CPU的性能？  针对上面两个问题，根据 .NET Guide 中的 Parallel Processing, Concurrency, and Async Programming in .NET 的内容，进一步深入理解 .NET 的下面三种机制：  异步编程 并行处理 多线程与线程">
<meta name="keywords" content="CSharp">
<meta property="og:type" content="article">
<meta property="og:title" content="Parallel Processing, Concurrency, and Async Programming in .NET - 1">
<meta property="og:url" content="http://sdfsd23few23.gitee.io/my_blog/2018/06/24/DotNet-Guide-Threading/index.html">
<meta property="og:site_name" content="Raymond&#39;s Blog">
<meta property="og:description" content=".NET 中的异步/多线程/并发处理(1) - 线程本文核心：  如何使用户交互界面具有良好的响应？ 如何最大化利用CPU的性能？  针对上面两个问题，根据 .NET Guide 中的 Parallel Processing, Concurrency, and Async Programming in .NET 的内容，进一步深入理解 .NET 的下面三种机制：  异步编程 并行处理 多线程与线程">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2018-06-27T13:10:47.382Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Parallel Processing, Concurrency, and Async Programming in .NET - 1">
<meta name="twitter:description" content=".NET 中的异步/多线程/并发处理(1) - 线程本文核心：  如何使用户交互界面具有良好的响应？ 如何最大化利用CPU的性能？  针对上面两个问题，根据 .NET Guide 中的 Parallel Processing, Concurrency, and Async Programming in .NET 的内容，进一步深入理解 .NET 的下面三种机制：  异步编程 并行处理 多线程与线程">






  <link rel="canonical" href="http://sdfsd23few23.gitee.io/my_blog/2018/06/24/DotNet-Guide-Threading/"/>



<script type="text/javascript" id="page.configurations">
  CONFIG.page = {
    sidebar: "",
  };
</script>

  <title>Parallel Processing, Concurrency, and Async Programming in .NET - 1 | Raymond's Blog</title>
  









  <noscript>
  <style type="text/css">
    .use-motion .motion-element,
    .use-motion .brand,
    .use-motion .menu-item,
    .sidebar-inner,
    .use-motion .post-block,
    .use-motion .pagination,
    .use-motion .comments,
    .use-motion .post-header,
    .use-motion .post-body,
    .use-motion .collection-title { opacity: initial; }

    .use-motion .logo,
    .use-motion .site-title,
    .use-motion .site-subtitle {
      opacity: initial;
      top: initial;
    }

    .use-motion {
      .logo-line-before i { left: initial; }
      .logo-line-after i { right: initial; }
    }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/my_blog/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Raymond's Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
    
      
        <p class="site-subtitle">CSharp & Java</p>
      
    
  </div>

  <div class="site-nav-toggle">
    <button aria-label="Toggle navigation bar">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>



<nav class="site-nav">
  
    <ul id="menu" class="menu">
      
        
        
        
          
          <li class="menu-item menu-item-home">
    <a href="/my_blog/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-home"></i> <br />Startseite</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-tags">
    <a href="/my_blog/tags/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />Tags</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-categories">
    <a href="/my_blog/categories/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-th"></i> <br />Kategorien</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-archives">
    <a href="/my_blog/archives/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />Archiv</a>
  </li>

      
      
    </ul>
  

  

  
</nav>



  



</div>
    </header>

    


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          
            

          
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://sdfsd23few23.gitee.io/my_blog/my_blog/2018/06/24/DotNet-Guide-Threading/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Raymond">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/my_blog/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Raymond's Blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Parallel Processing, Concurrency, and Async Programming in .NET - 1
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Veröffentlicht am</span>
              

              
                
              

              <time title="Post created: 2018-06-24 18:14:09" itemprop="dateCreated datePublished" datetime="2018-06-24T18:14:09+08:00">2018-06-24</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Updated at: 2018-06-27 21:10:47" itemprop="dateModified" datetime="2018-06-27T21:10:47+08:00">2018-06-27</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">in</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/my_blog/categories/Coding/" itemprop="url" rel="index"><span itemprop="name">Coding</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="NET-中的异步-多线程-并发处理-1-线程"><a href="#NET-中的异步-多线程-并发处理-1-线程" class="headerlink" title=".NET 中的异步/多线程/并发处理(1) - 线程"></a>.NET 中的异步/多线程/并发处理(1) - 线程</h1><p>本文核心：</p>
<ol>
<li>如何使用户交互界面具有良好的响应？</li>
<li>如何最大化利用CPU的性能？</li>
</ol>
<p>针对上面两个问题，根据 .NET Guide 中的 <a href="https://docs.microsoft.com/en-us/dotnet/standard/parallel-processing-and-concurrency" target="_blank" rel="noopener">Parallel Processing, Concurrency, and Async Programming in .NET</a> 的内容，进一步深入理解 .NET 的下面三种机制：</p>
<ol>
<li>异步编程</li>
<li>并行处理</li>
<li>多线程与线程同步机制。</li>
</ol>
<h2 id="线程"><a href="#线程" class="headerlink" title="线程"></a>线程</h2><h3 id="1-托管线程基础"><a href="#1-托管线程基础" class="headerlink" title="1. 托管线程基础"></a>1. 托管线程基础</h3><h4 id="Threads-and-Threading"><a href="#Threads-and-Threading" class="headerlink" title="Threads and Threading"></a>Threads and Threading</h4><p>操作系统使用进程来分离正在执行的不同应用程序。线程是操作系统分配处理器时间的基本单位，并且多个线程可以在该进程内执行。每个线程维护自己的：异常处理、调度优先级以及一组用于保存线程上下文的结构。线程上下文：存储在所属进程的地址空间中的，线程能够无缝恢复执行的所有信息（一组CPU寄存器和堆栈）。</p>
<p>.NET Framework进一步将操作系统进程细分为由System.AppDomain表示的称为应用程序域的轻量级托管子进程。一个或多个托管线程（由System.Threading.Thread表示）可以在同一个托管进程中的一个或任意数量的应用程序域中运行。尽管每个应用程序域都使用单个线程启动，但该应用程序域中的代码可以创建其他应用程序域和其他线程。其结果是托管线程可以在同一个托管进程中的应用程序域之间自由移动;但只有一个线程在多个应用程序域中移动。</p>
<p>支持抢先式多任务的操作系统可以同时执行多个进程中的多个线程。它通过在需要它的线程之间分配可用的处理器时间，为每个线程分配一个处理器时间片。当前正在执行的线程在其时间片消逝时挂起，另一个线程恢复运行。当系统从一个线程切换到另一个线程时，它保存抢先线程的线程上下文，并重新加载线程队列中下一个线程的已保存线程上下文。</p>
<p>时间片的长度取决于操作系统和处理器。由于每个时间片都很小，因此不管是一个处理器还是多处理器，多个线程看起来是同时执行的。但是实质上只有多处理器的系统实际上会有两个以上的线程同时执行，线程分布在可用的处理器中。</p>
<p>多线程的优缺点：使用尽可能少的线程，从而最大限度地减少操作系统资源的使用并提高性能。线程在设计应用程序时也需要考虑资源需求和潜在的冲突。资源需求如下：</p>
<ol>
<li>进程，AppDomain对象和线程所需的上下文信息，都消耗系统的内存。因此，可以创建的进程，AppDomain对象和线程的数量受可用内存的限制。 </li>
<li>跟踪大量的线程会消耗大量的处理器时间。如果线程太多，他们中的大多数不会取得重大进展。如果大多数当前线程都在一个进程中，则其他进程中的线程的调度次数会减少。</li>
<li>控制许多线程的代码执行非常复杂，并且可能成为许多错误的来源。 </li>
<li>销毁线程时需要注意会发生什么，而且要注意处理线程中的异常。 </li>
</ol>
<p>提供对资源的共享访问可能会产生冲突。为避免冲突，您必须同步或控制对共享资源的访问。如果无法正确同步访问（在相同或不同的应用程序域中），可能会导致问题，如死锁（其中两个线程停止响应，而每个线程都会等待另一个线程完成）以及竞争条件（由于意外而出现异常结果严重依赖两个事件的时间）。系统提供可用于协调多个线程之间资源共享的同步对象。减少线程数量可以更容易地同步资源。 </p>
<p>需要同步的资源包括：</p>
<ol>
<li>系统资源（如通信端口）。 </li>
<li>资源由多个进程共享（如文件句柄）。 </li>
<li>由多个线程访问的单个应用程序域（例如全局，静态和实例字段）的资源。</li>
</ol>
<p>一般来说，使用ThreadPool类是处理多个线程的最简单方法，用于处理相对较短的任务，这些任务不会阻止其他线程，并且不需要指定特定的任务调度。</p>
<p>但是，如果是以下几种原因，那么你可能需要自行创建线程：</p>
<ol>
<li>如果您需要一项任务来获得特定的优先级。 </li>
<li>如果您有一项任务可能会运行很长时间（并因此阻止其他任务）。 </li>
<li>如果您需要将线程放入单线程单元（所有ThreadPool线程都在多线程单元中）。 </li>
<li>如果您需要与该线程关联的稳定身份。例如，您应该使用专用线程来中止该线程，暂停或按名称发现它。 </li>
</ol>
<h4 id="线程数据同步"><a href="#线程数据同步" class="headerlink" title="线程数据同步"></a>线程数据同步</h4><p>.NET 提供了几种策略来同步对实例和静态成员的访问：</p>
<ol>
<li>同步代码区域。您可以对此类使用Monitor类或编译器支持来仅同步需要它的代码块，从而提高性能。 </li>
<li>手动同步。您可以使用.NET Framework类库提供的同步对象。请参阅同步基元概述，其中包括对Monitor类的讨论。 </li>
<li>同步的上下文。您可以使用SynchronizationAttribute为ContextBoundObject对象启用简单的自动同步。 System.Collections.Concurrent命名空间中的Collection类。这些类提供了内置的同步添加和删除操作。有关更多信息，请参阅<a href="https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/index" target="_blank" rel="noopener">Thread-Safe Collections</a>。</li>
</ol>
<h4 id="同步基元概述"><a href="#同步基元概述" class="headerlink" title="同步基元概述"></a>同步基元概述</h4><h5 id="Locking"><a href="#Locking" class="headerlink" title="Locking"></a>Locking</h5><p>独占锁：</p>
<ol>
<li>lock/Monitor：</li>
<li>Mutex/Mutexes：互斥</li>
<li>SpinLock：自旋锁，如果锁保持很短的时间，SpinLock可以提供比阻塞更好的性能。但是，如果锁持续数十个周期，SpinLock的性能与Monitor相当。</li>
</ol>
<p>非独占锁：不必是排他性的锁。允许有限数量的线程在并发访问资源通常很有用。Semaphores and reader-writer locks 旨在控制这种资源池式访问。</p>
<ol>
<li><a href="https://docs.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives#readerwriterlock-class" target="_blank" rel="noopener">ReaderWriterLock Class</a></li>
<li><a href="https://docs.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives#semaphore-class" target="_blank" rel="noopener">Semaphore Class</a></li>
</ol>
<h5 id="Signaling"><a href="#Signaling" class="headerlink" title="Signaling"></a>Signaling</h5><ol>
<li>Wait Handles</li>
<li>Event Wait Handles : AutoResetEvent 和 ManualResetEvent</li>
<li>Barrier : Barrier类提供了一种循环同步多个线程的方法，以便它们在同一个点处阻塞并等待所有其他线程完成。比如：当一个或多个线程在继续到算法的下一个阶段之前需要另一个线程的结果。</li>
</ol>
<p>下面是 Barrier 类的一个例子：</p>
<pre><code>// Create the Barrier object, and supply a post-phase delegate 
// to be invoked at the end of each phase.
Barrier barrier = new Barrier(2, (bar) =&gt; 
    {
        // Examine results from all threads, determine 
        // whether to continue, create inputs for next phase, etc. 
        if (someCondition)
            success = true;
    });       


// Define the work that each thread will perform. (Threads do not
// have to all execute the same method.)
void CrunchNumbers(int partitionNum)
{
    // Up to System.Int64.MaxValue phases are supported. We assume
    // in this code that the problem will be solved before that.
    while (success == false)
    {
        // Begin phase:
        // Process data here on each thread, and optionally
        // store results, for example:
        results[partitionNum] = ProcessData(data[partitionNum]);

        // End phase:
        // After all threads arrive,post-phase delegate
        // is invoked, then threads are unblocked. Overloads
        // accept a timeout value and/or CancellationToken.
        barrier.SignalAndWait();
    }
}

// Perform n tasks to run in in parallel. For simplicity
// all threads execute the same method in this example.
static void Main()
{
    var app = new BarrierDemo();
    Thread t1 = new Thread(() =&gt; app.CrunchNumbers(0));
    Thread t2 = new Thread(() =&gt; app.CrunchNumbers(1));
    t1.Start();
    t2.Start();

}
</code></pre><h5 id="Lightweight-Synchronization-Types"><a href="#Lightweight-Synchronization-Types" class="headerlink" title="Lightweight Synchronization Types"></a>Lightweight Synchronization Types</h5><p>从 .NET Framework 4 开始，您可以使用同步基元，通过尽可能避免昂贵地依赖Win32内核对象（如等待句柄）来提供快速性能。一般来说，当等待时间较短时，只有在尝试原始同步类型并发现不合格时，才应使用这些类型。轻量级类型不能用于需要跨进程通信的场景。 </p>
<ol>
<li>System.Threading.SemaphoreSlim是System.Threading.Semaphore的轻量级版本。 </li>
<li>System.Threading.ManualResetEventSlim是System.Threading.ManualResetEvent的轻量级版本。 </li>
<li>System.Threading.CountdownEvent表示一个事件，当其计数为零时，该事件将变为信号。 </li>
<li>System.Threading.Barrier允许多个线程彼此同步，而无需主线程控制。屏障阻止每个线程继续，直到所有线程都达到指定的点</li>
</ol>
<h5 id="SpinWait"><a href="#SpinWait" class="headerlink" title="SpinWait"></a>SpinWait</h5><p>从.NET Framework 4 开始，您可以在线程必须等待事件发送信号或满足条件时使用 System.Threading.SpinWait 结构，但实际等待时间应小于通过使用等待句柄或以其他方式阻止当前线程所需的等待时间。通过使用SpinWait，您可以在等待时指定短时间等待，然后仅当在指定时间内未满足条件时才产生（例如，通过等待或休眠）。</p>
<pre><code>using System;
using System.Threading;
using System.Threading.Tasks;

class SpinWaitDemo
{
    // Demonstrates:
    //      SpinWait construction
    //      SpinWait.SpinOnce()
    //      SpinWait.NextSpinWillYield
    //      SpinWait.Count
    static void Main()
    {
        bool someBoolean = false;
        int numYields = 0;

        // First task: SpinWait until someBoolean is set to true
        Task t1 = Task.Factory.StartNew(() =&gt;
        {
            SpinWait sw = new SpinWait();
            while (!someBoolean)
            {
                // The NextSpinWillYield property returns true if
                // calling sw.SpinOnce() will result in yielding the
                // processor instead of simply spinning.
                if (sw.NextSpinWillYield) numYields++;
                sw.SpinOnce();
            }

            // As of .NET Framework 4: After some initial spinning, SpinWait.SpinOnce() will yield every time.
            Console.WriteLine(&quot;SpinWait called {0} times, yielded {1} times&quot;, sw.Count, numYields);
        });

        // Second task: Wait 100ms, then set someBoolean to true
        Task t2 = Task.Factory.StartNew(() =&gt;
        {
            Thread.Sleep(100);
            someBoolean = true;
        });

        // Wait for tasks to complete
        Task.WaitAll(t1, t2);
    }
}
</code></pre><h5 id="Interlocked"><a href="#Interlocked" class="headerlink" title="Interlocked"></a>Interlocked</h5><p>Interlocked 操作是通过 Interlocked 类的静态方法在内存上执行的简单原子操作。这些原子操作包括增加，增加和减少，交换，取决于比较的条件交换，以及在32位平台上读取64位值的操作。 </p>
<p><code>注：原子性的保证仅限于个别操作;当多个操作必须作为一个单元执行时，必须使用更粗粒度的同步机制。</code> </p>
<p>虽然这些操作都不是锁或信号，但它们可以用来构造锁和信号。由于它们是Windows操作系统的本机特性，因此 Interlocked 操作非常快速。 </p>
<p>Interlocked 操作可以与 volatile memory 一起使用，以编写展现出强大的非阻塞，高并发的应用程序。但是，它们需要复杂的低级编程，所以对于大多数用途而言，简单的 lock 是更好的选择。</p>
<p>下面是使用 Interlocked 类的例子：</p>
<pre><code>using System;
using System.Threading;

namespace InterlockedExchange_Example
{
    class MyInterlockedExchangeExampleClass
    {
        //0 for false, 1 for true.
        private static int usingResource = 0;

        private const int numThreadIterations = 5;
        private const int numThreads = 10;

        static void Main()
        {
            Thread myThread;
            Random rnd = new Random();

            for(int i = 0; i &lt; numThreads; i++)
            {
                myThread = new Thread(new ThreadStart(MyThreadProc));
                myThread.Name = String.Format(&quot;Thread{0}&quot;, i + 1);

                //Wait a random amount of time before starting next thread.
                Thread.Sleep(rnd.Next(0, 1000));
                myThread.Start();
            }
        }

        private static void MyThreadProc()
        {
            for(int i = 0; i &lt; numThreadIterations; i++)
            {
                UseResource();

                //Wait 1 second before next attempt.
                Thread.Sleep(1000);
            }
        }

        //A simple method that denies reentrancy.
        static bool UseResource()
        {
            //0 indicates that the method is not in use.
            if(0 == Interlocked.Exchange(ref usingResource, 1))
            {
                Console.WriteLine(&quot;{0} acquired the lock&quot;, Thread.CurrentThread.Name);

                //Code to access a resource that is not thread safe would go here.

                //Simulate some work
                Thread.Sleep(500);

                Console.WriteLine(&quot;{0} exiting lock&quot;, Thread.CurrentThread.Name);

                //Release the lock
                Interlocked.Exchange(ref usingResource, 0);
                return true;
            }
            else
            {
                Console.WriteLine(&quot;   {0} was denied the lock&quot;, Thread.CurrentThread.Name);
                return false;
            }
        }

    }
}  
</code></pre><h4 id="Foreground-and-Background-Threads"><a href="#Foreground-and-Background-Threads" class="headerlink" title="Foreground and Background Threads"></a>Foreground and Background Threads</h4><p>托管线程可以是后台线程或前台线程。后台线程与前台线程相同，只有一个例外：后台线程不保持托管执行环境的运行。一旦所有前台线程在托管进程中停止，系统将停止所有后台线程并关闭。</p>
<p><strong>注意</strong>:当运行时由于进程关闭而停止后台线程时，线程中不会引发异常。但是，当线程由于AppDomain.Unload方法卸载应用程序域而停止时，ThreadAbortException会在前台和后台线程中抛出。</p>
<p>使用Thread.IsBackground属性来确定线程是后台线程还是前台线程，还是更改其状态。通过将其IsBackground属性设置为true，可以随时将线程更改为后台线程。</p>
<p>属于托管线程池的线程（即其IsThreadPoolThread属性为true的线程）是后台线程。所有从非托管代码进入托管执行环境的线程都被标记为后台线程。通过创建和启动一个新的Thread对象生成的所有线程默认情况下都是前台线程。</p>
<p>如果您使用线程来监视某个活动（如套接字连接），请将其IsBackground属性设置为true，以便该线程不会阻止您的进程终止。</p>
<h4 id="线程取消的机制"><a href="#线程取消的机制" class="headerlink" title="线程取消的机制"></a>线程取消的机制</h4><p>从.NET Framework 4开始，.NET Framework使用统一模型来协同取消异步或长时间运行的同步操作。该模型基于称为 cancellation token 的轻量级对象。调用一个或多个可取消操作的对象（例如通过创建新线程或任务）将 token 传递给每个操作。单独的操作可以将令牌的副本传递给其他操作。稍后，创建令牌的对象可以用它来请求操作停止他们正在做的事情。只有请求对象才能发出取消请求，并且每个监听者都有责任注意请求并以适当和及时的方式作出响应。</p>
<p>实施协作取消模式的一般模式是：</p>
<ol>
<li>实例化一个CancellationTokenSource对象，该对象管理并向各个取消令牌发送取消通知。</li>
<li>将CancellationTokenSource.Token属性返回的令牌传递给侦听取消的每个任务或线程。</li>
<li>为每个任务或线程提供响应取消的机制。</li>
<li>调用CancellationTokenSource.Cancel方法来提供取消通知。</li>
</ol>
<p><strong>需要注意</strong> CancellationTokenSource类实现了IDisposable接口。 当您完成使用取消标记来源以释放其拥有的任何非托管资源时，应确保调用CancellationTokenSource.Dispose方法。</p>
<p>示例代码：</p>
<pre><code>using System;
using System.Threading;

public class Example
{
public static void Main()
{
    // Create the token source.
    CancellationTokenSource cts = new CancellationTokenSource();

    // Pass the token to the cancelable operation.
    ThreadPool.QueueUserWorkItem(new WaitCallback(DoSomeWork), cts.Token);
    Thread.Sleep(2500);

    // Request cancellation.
    cts.Cancel();
    Console.WriteLine(&quot;Cancellation set in token source...&quot;);
    Thread.Sleep(2500);
    // Cancellation should have happened, so call Dispose.
    cts.Dispose();
}

// Thread 2: The listener
static void DoSomeWork(object obj)
{
    CancellationToken token = (CancellationToken)obj;

    for (int i = 0; i &lt; 100000; i++) {
        if (token.IsCancellationRequested)
        {
            Console.WriteLine(&quot;In iteration {0}, cancellation has been requested...&quot;,
                            i + 1);
            // Perform cleanup if necessary.
            //...
            // Terminate the operation.
            break;
        }
        // Simulate some work.
        Thread.SpinWait(500000);
    }
}
}
// The example displays output like the following:
//       Cancellation set in token source...
//       In iteration 1430, cancellation has been requested...
</code></pre><h4 id="托管线程的最佳实践"><a href="#托管线程的最佳实践" class="headerlink" title="托管线程的最佳实践"></a>托管线程的最佳实践</h4><h5 id="死锁和竞态条件"><a href="#死锁和竞态条件" class="headerlink" title="死锁和竞态条件"></a>死锁和竞态条件</h5><p>死锁：当两个线程中的每一个尝试锁定另一个已锁定的资源时，都会发生死锁。 这两个线程都无法取得进一步的进展。</p>
<p>托管线程类的许多方法都会提供超时来帮助您检测死锁。 例如，以下代码尝试获取名为lockObject的对象的锁定。 如果锁定未在300毫秒内获得，则Monitor.TryEnter返回false。</p>
<pre><code>if (Monitor.TryEnter(lockObject, 300)) {  
    try {  
        // Place code protected by the Monitor here.  
    }  
    finally {  
        Monitor.Exit(lockObject);  
    }  
}  
else {  
    // Code to execute if the attempt times out.  
}  
</code></pre><h5 id="竟态条件"><a href="#竟态条件" class="headerlink" title="竟态条件"></a>竟态条件</h5><p>通过使用Interlocked类的方法（如Interlocked.Increment）可以轻松避免竞争条件。要了解用于在多个线程之间同步数据的其他技术，请参阅同步多线程数据。</p>
<p>当您同步多个线程的活动时，也可能发生竞争状况。每当你写一行代码时，你必须考虑如果一个线程在执行该行之前被抢先（或者在组成该行的任何单个机器指令之前）并且另一个线程超过它，可能发生的情况。</p>
<h4 id="进阶-Thread-中的异常处理"><a href="#进阶-Thread-中的异常处理" class="headerlink" title="进阶 - Thread 中的异常处理"></a>进阶 - Thread 中的异常处理</h4><p><a href="https://docs.microsoft.com/en-us/dotnet/standard/threading/exceptions-in-managed-threads" target="_blank" rel="noopener">Exceptions in Managed Threads</a></p>
<h4 id="进阶-Thread-Local-Storage"><a href="#进阶-Thread-Local-Storage" class="headerlink" title="进阶 - Thread Local Storage"></a>进阶 - Thread Local Storage</h4><p><a href="https://docs.microsoft.com/en-us/dotnet/standard/threading/thread-local-storage-thread-relative-static-fields-and-data-slots" target="_blank" rel="noopener">Thread Local Storage: Thread-Relative Static Fields and Data Slots</a></p>
<h3 id="2-使用线程"><a href="#2-使用线程" class="headerlink" title="2. 使用线程"></a>2. 使用线程</h3><h3 id="3-线程对象和特性"><a href="#3-线程对象和特性" class="headerlink" title="3. 线程对象和特性"></a>3. 线程对象和特性</h3>
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/my_blog/tags/CSharp/" rel="tag"># CSharp</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/my_blog/2018/06/24/DotNet-Guide-Parallel-Programming/" rel="next" title="Parallel Processing, Concurrency, and Async Programming in .NET - 3">
                <i class="fa fa-chevron-left"></i> Parallel Processing, Concurrency, and Async Programming in .NET - 3
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/my_blog/2018/08/10/DotNet-Guide-Memory-Management/" rel="prev" title="Memory Management and Garbage Collection in .NET - 1">
                Memory Management and Garbage Collection in .NET - 1 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Inhaltsverzeichnis
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Übersicht
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">Raymond</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          
            <nav class="site-state motion-element">
              
                <div class="site-state-item site-state-posts">
                
                  <a href="/my_blog/archives/">
                
                    <span class="site-state-item-count">12</span>
                    <span class="site-state-item-name">Artikel</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-categories">
                  <a href="/my_blog/categories/index.html">
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">5</span>
                    <span class="site-state-item-name">Kategorien</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-tags">
                  <a href="/my_blog/Tags/index.html">
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">11</span>
                    <span class="site-state-item-name">Tags</span>
                  </a>
                </div>
              
            </nav>
          

          

          

          
          

          
          

          
            
          
          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#NET-中的异步-多线程-并发处理-1-线程"><span class="nav-number">1.</span> <span class="nav-text">.NET 中的异步/多线程/并发处理(1) - 线程</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#线程"><span class="nav-number">1.1.</span> <span class="nav-text">线程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-托管线程基础"><span class="nav-number">1.1.1.</span> <span class="nav-text">1. 托管线程基础</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Threads-and-Threading"><span class="nav-number">1.1.1.1.</span> <span class="nav-text">Threads and Threading</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#线程数据同步"><span class="nav-number">1.1.1.2.</span> <span class="nav-text">线程数据同步</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#同步基元概述"><span class="nav-number">1.1.1.3.</span> <span class="nav-text">同步基元概述</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#Locking"><span class="nav-number">1.1.1.3.1.</span> <span class="nav-text">Locking</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Signaling"><span class="nav-number">1.1.1.3.2.</span> <span class="nav-text">Signaling</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Lightweight-Synchronization-Types"><span class="nav-number">1.1.1.3.3.</span> <span class="nav-text">Lightweight Synchronization Types</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#SpinWait"><span class="nav-number">1.1.1.3.4.</span> <span class="nav-text">SpinWait</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Interlocked"><span class="nav-number">1.1.1.3.5.</span> <span class="nav-text">Interlocked</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Foreground-and-Background-Threads"><span class="nav-number">1.1.1.4.</span> <span class="nav-text">Foreground and Background Threads</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#线程取消的机制"><span class="nav-number">1.1.1.5.</span> <span class="nav-text">线程取消的机制</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#托管线程的最佳实践"><span class="nav-number">1.1.1.6.</span> <span class="nav-text">托管线程的最佳实践</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#死锁和竞态条件"><span class="nav-number">1.1.1.6.1.</span> <span class="nav-text">死锁和竞态条件</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#竟态条件"><span class="nav-number">1.1.1.6.2.</span> <span class="nav-text">竟态条件</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#进阶-Thread-中的异常处理"><span class="nav-number">1.1.1.7.</span> <span class="nav-text">进阶 - Thread 中的异常处理</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#进阶-Thread-Local-Storage"><span class="nav-number">1.1.1.8.</span> <span class="nav-text">进阶 - Thread Local Storage</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-使用线程"><span class="nav-number">1.1.2.</span> <span class="nav-text">2. 使用线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-线程对象和特性"><span class="nav-number">1.1.3.</span> <span class="nav-text">3. 线程对象和特性</span></a></li></ol></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Raymond</span>

  

  
</div>




  <div class="powered-by">Erstellt mit  <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> v3.7.1</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://theme-next.org">NexT.Pisces</a> v6.3.0</div>




        








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>


























  
  
    <script type="text/javascript" src="/my_blog/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/my_blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/my_blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  


  


  <script type="text/javascript" src="/my_blog/js/src/utils.js?v=6.3.0"></script>

  <script type="text/javascript" src="/my_blog/js/src/motion.js?v=6.3.0"></script>



  
  


  <script type="text/javascript" src="/my_blog/js/src/affix.js?v=6.3.0"></script>

  <script type="text/javascript" src="/my_blog/js/src/schemes/pisces.js?v=6.3.0"></script>



  
  <script type="text/javascript" src="/my_blog/js/src/scrollspy.js?v=6.3.0"></script>
<script type="text/javascript" src="/my_blog/js/src/post-details.js?v=6.3.0"></script>



  


  <script type="text/javascript" src="/my_blog/js/src/bootstrap.js?v=6.3.0"></script>



  



	





  





  










  





  

  

  

  

  
  

  

  

  

  

  

</body>
</html>
